package com.github.defense.plugin.gray.netflix.rest;

import com.github.defense.plugin.gray.constants.GrayClientConstant;
import com.github.defense.plugin.gray.context.RoutingHandler;
import com.github.defense.plugin.gray.context.RoutingLocalContext;
import com.github.defense.plugin.gray.enums.GrayType;
import com.github.defense.plugin.gray.holder.GrayEnvContextHolder;
import com.github.defense.plugin.gray.request.GrayHttpRequest;
import com.github.defense.plugin.gray.utils.WebUtils;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;
import java.net.URI;

/**
 *  在使用RestTemplate的时候通过实现ClientHttpRequestInterceptor
 *  主要作用是用来获取request的相关信息，为后面的路由提供数据基础。
 *  只有当以RestTemplate 请求的时候进入路由之前才会走这
 * @Author: lettger
 * @Date: 2021/6/19 5:36 下午
 */
public class GrayClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

    private RoutingHandler handler;

    public GrayClientHttpRequestInterceptor(RoutingHandler handler) {
        this.handler = handler;
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        // 未开启灰度
        if(!GrayEnvContextHolder.getEnvBool(GrayClientConstant.GRAY_CLIENT_ENABLE)){
            return execution.execute(request, body);
        }
        URI uri = request.getURI();
        GrayHttpRequest grayRequest = new GrayHttpRequest();
        grayRequest.setUri(uri);
        grayRequest.setServiceId(uri.getHost());
        grayRequest.setParameters(WebUtils.getQueryParams(uri.getQuery()));
        grayRequest.setMethod(request.getMethod().name());
        grayRequest.addHeaders(request.getHeaders());
        RoutingLocalContext context = RoutingLocalContext.builder().grayType(GrayType.REST).request(grayRequest).build();
        return handler.execute(context, () -> execution.execute(request, body));
    }
}
